使用Python Geotiff转换数字高程数据的基本地图信息

您所在的位置:网站首页 python 安装elementtree 使用Python Geotiff转换数字高程数据的基本地图信息

使用Python Geotiff转换数字高程数据的基本地图信息

2023-04-02 01:04| 来源: 网络整理| 查看: 265

2020.06.10更新

由于此安排已从北向南颠倒,因此添加了紧急更正。

介绍

标题中的数据在此站点上分发。 提供日本非常详细,准确的海拔数据(DEM)。 内务和通信部统计局为每个二级分区网格下载了一个zip格式文件。它包含xml格式的高程数据。稍后将描述区域网格。

代码在本文结尾。一个例子如下。

(由于文件名也用作元信息,因此请将其应用到下载的文件中)

命令

1python zdem2tif.py FG-GML-1234-56-DEM10B.zip FG-GML-6543-21-DEM5A.zip ...

每个zip文件(=次要分区区域网格)将输出一个geotiff图像。 支持5m和10m分辨率。 我们已经确认了python3系列的操作。必须安装gdal软件包。

这次,我对这个站点上的代码进行了很多引用。但是,如果保持原样,则在数据丢失的情况下会发生错误,因此该代码已得到修复。

似乎还有其他各种工具,但是创建此代码是因为它可以在命令上执行,可以与外国人共享,因为它是用英语编写的,因此无需解压缩。

另外,正如我在发布后注意到的那样,qiita已经有一篇有关基本地图信息和python的文章。文件格式的说明在此处更详细。

关于区域网格

本文档中给出了详细定义。 根据空间分辨率在1到3阶分区中定义区域网格。 主网格被分配了4位数字的分区代码,辅助网格被分配了另外2位数字,第三网格被分配了另外2位数字。 可以使用车厢代码的编号来知道车厢四个角的纬度和经度。

源代码说明

将来,分布式数据的规范可能会发生变化,并且有可能在作者未确认的领域中不受支持,因此我将简要解释代码。

(convert)的总流量为

从zip文件名获取区域网格信息和DEM分辨率 定义一个输出文件数组(到目前为止DEMOutArray,mesh_info_from_zipname) 关于zip文件(for filename in filelist)中xml文件的循环 从xml文件(XMLContents,read_xml)获取所需的信息 为每个xml文件(DEMInArray)生成DEM数组 覆盖输出数组(update_raster) 以Tiff格式保存(save_raster) 从zip文件名

获取区域网格信息和DEM分辨率

读取4位主分区代码和2位辅分区代码以计算四个角的纬度和经度。 此外,通过将文件名写为DEM5X还是DEM10X来解释分辨率。 对于每种分辨率,一个xml文件的数组大小都是固定的(例如,在10mDEM的情况下,假定zip中只有一个xml)。

定义输出文件数组

预先创建一个次级部分的大小。 在5mDEM的情况下,假设一个zip(第二分区)中最多包含10 x 10 xml(第三分区)。但是,似乎有许多区域尚未被观察到,并且在某些情况下仅存在约10个xml。 -9999的异常值用于对应于不存在xml的区域的位置。

关于zip文件中的xml文件Loop

第一次,我了解了默认包含的模块

zipfile。 通过使用此功能,您无需解压缩每个文件就可以读取zip中的文件。

从xml文件

获取所需的信息

对于

5mDEM,请读取文件名中描述的第三级分区代码的最后两位,并确定输出数组中的插入位置。如上所述,在10mDEM的情况下,首先假设没有第三级分区代码的描述,而只有一个xml。 暂时获取文本类型的必要信息。假定xml等中的标记规则如代码中所示。如果您使用不同的规则阅读xml,它应该立即显示为错误。

为每个xml文件生成DEM数组3??769113

使用

xml文件中描述的信息生成数组。 文件规范具有DEM数据的定义。据此,每个像素的土地分割是{地表,表面,海平面,内陆水面,无数据等},并且对于值未定义的地方输入-9999的数量。 。

在最初引用的代码中,根据是否为"地面"来获取DEM信息,但是在此代码中,根据xml中的DEM值是否为-9999对其进行划分("其他")。因为在指示的区域中有DEM值。说"其他"的原因未知)。 对于未定义DEM的地方,将应用离群值-1,并将离群值的使用与首先没有上述xml文件的情况分开。

覆盖输出阵列

关于

数组的方向,假定纬度方向定义为北。从xml获得的数据中有gml:sequenceRule,并且将其写为'+x-y'的事实也支持它。如果这是'+x+y'等,则可能是朝南,但我尚未围绕该条件进行划分。

以Tiff格式保存

无话可说。

输出tiff的图

转换后的文件,其顶部为5mDEM,底部为10mDEM,下载了相同的二级分割区域(几乎没有编辑,如轴值)。负值被掩盖。可以看出,每种分辨率下数据的丰度都因区域而异。 在下载之前很高兴知道,但是某个地方缺少任何信息吗? .. ..

整个源代码

最后,整个代码。

zdem2tif.py

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197import os import sys import zipfile import numpy as np import xml.etree.ElementTree as et import osgeo.gdal import osgeo.osr class XMLContents(object):     def __init__(self):         self.ns = {                    'ns': 'http://fgd.gsi.go.jp/spec/2008/FGD_GMLSchema',                    'gml': 'http://www.opengis.net/gml/3.2',                    'xsi': 'http://www.w3.org/2001/XMLSchema-instance',                    'xlink': 'http://www.w3.org/1999/xlink'                    }     def read_xml(self, zf, filename, dem_mode):         if dem_mode == 'DEM10':             self.posix = 0             self.posiy = 0         elif dem_mode == 'DEM5':             _split = os.path.basename(filename).split('-')             self.posix = int(_split[4][1])             self.posiy = int(_split[4][0])         with zf.open(filename, 'r') as file:             self.text = file.read().decode('utf_8')             self.root = et.fromstring(self.text)             self.dem = self.root.find('ns:DEM', self.ns)             self.coverage = self.dem.find('ns:coverage', self.ns)             self.envelope = self.coverage.find(                 'gml:boundedBy//gml:Envelope', self.ns)             self.lower = self.envelope.find('gml:lowerCorner', self.ns).text             self.upper = self.envelope.find('gml:upperCorner', self.ns).text             self.grid = self.coverage.find(                 'gml:gridDomain//gml:Grid//gml:limits//gml:GridEnvelope', self.ns)             self.low = self.grid.find('gml:low', self.ns).text             self.high = self.grid.find('gml:high', self.ns).text             self.tuplelist = self.coverage.find(                 'gml:rangeSet//gml:DataBlock//gml:tupleList', self.ns).text             self.gridfunc = self.coverage.find(                 'gml:coverageFunction//gml:GridFunction', self.ns)             self.rule = self.gridfunc.find('gml:sequenceRule', self.ns)             self.start = self.gridfunc.find('gml:startPoint', self.ns).text             if self.rule.attrib['order'] != '+x-y':                 print('warning sequence order not +x-y')             if self.rule.text != 'Linear':                 print('warning sequence rule not Linear')             file.close() class DEMInArray(object):     def __init__(self, contents):         self._noValue = -1.         self.llat, self.llon = np.array(             contents.lower.split(' '), dtype=np.float64)         self.ulat, self.ulon = np.array(             contents.upper.split(' '), dtype=np.float64)         self.lowx, self.lowy = np.array(             contents.low.split(' '), dtype=np.int)         self.highx, self.highy = np.array(             contents.high.split(' '), dtype=np.int)         self.sizex, self.sizey = self.get_size()         self.x_init, self.y_init = np.array(             contents.start.split(' '), dtype=np.int)         self.datapoints = contents.tuplelist.splitlines()         self.raster = self.get_raster()     def get_size(self):         sizex = self.highx - self.lowx + 1         sizey = self.highy - self.lowy + 1         return sizex, sizey     def get_raster(self):         _x, _y = self.x_init, self.y_init         raster = np.zeros([self.sizey, self.sizex])         raster.fill(self._noValue)         for dp in self.datapoints:             if _y > self.highy:                 print('DEM datapoints are unexpectedly too long')                 break             s = dp.split(',')             if len(s) == 1:                 continue             desc, value = s[0], np.float64(s[1])             # if desc == '地表面':             raster[_y, _x] = value if value > -9998 else self._noValue             _x += 1             if _x > self.highx:                 _x = 0                 _y += 1         return raster class DEMOutArray(object):     def __init__(self):         self._fillValue = -9999.     def initialize_raster(self):         raster = np.zeros([self.sizey, self.sizex])         raster.fill(self._fillValue)         return raster     def get_trans(self):         # +x-y         return [self.llon, self.resx, 0, self.ulat, 0, -self.resy]     def update_raster(self, tile, posiy, posix):         xmin = posix * tile.shape[1]         ymin = posiy * tile.shape[0]         xmax = xmin + tile.shape[1]         ymax = ymin + tile.shape[0]         self.raster[ymin:ymax, xmin:xmax] = tile[::-1]     def get_size(self):         sizex = (self.highx - self.lowx + 1) * self.tilex         sizey = (self.highy - self.lowy + 1) * self.tiley         return sizex, sizey     def mesh_info_from_zipname(self, zipname):         '''         Ref: Table 4 of https://www.stat.go.jp/data/mesh/pdf/gaiyo1.pdf         '''         _split = os.path.basename(zipname).split('-')         _lat1 = int(_split[2][:2])         _lon1 = int(_split[2][2:])         _lat2 = int(_split[3][0])         _lon2 = int(_split[3][1])         self.llat = _lat1 * 0.66666666666 + _lat2 * 0.08333333333         self.llon = _lon1 + 100. + _lon2 * 0.125         self.ulat = self.llat + 0.08333333333         self.ulon = self.llon + 0.125         if _split[4][:5] == 'DEM10':             self.mode = 'DEM10'             self.tilex, self.tiley = 1, 1             self.lowx, self.lowy = 0, 0             self.highx, self.highy = 1124, 749             self.sizex, self.sizey = self.get_size()             self.resx, self.resy = 1.1111111111e-04, 1.1111111111e-04         elif _split[4][:4] == 'DEM5':             self.mode = 'DEM5'             self.tilex, self.tiley = 10, 10             self.lowx, self.lowy = 0, 0             self.highx, self.highy = 224, 149             self.sizex, self.sizey = self.get_size()             self.resx, self.resy = 5.5555555555e-05, 5.5555555555e-05         else:             raise ValueError('Unexpected definition of DEM:', _split[4])         self.raster = self.initialize_raster()     def save_raster(self, out_filename):         trans = self.get_trans()         srs = osgeo.osr.SpatialReference()         srs.ImportFromEPSG(4612)         driver = osgeo.gdal.GetDriverByName('GTiff')         output = driver.Create(out_filename, self.sizex, self.sizey,                                1, osgeo.gdal.GDT_Float32) #         output.GetRasterBand(1).WriteArray(self.raster)


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3